import {Dep} from "./dep";
import {defineReactive, def} from "./index";
import {hasOwn, isArray, isPlainObject} from "../../shared/util";
import {walkArray} from "./array";
import {VNode} from "../../type/VNode";

export class Observer {

    /**
     * 为 Object 或 Array 创建一个观察者对象，
     * 用于收集 Object 的属性变化 或者 Array 的 数据变化
     * @param {any} value
     */
    constructor(value) {
        this.dep = new Dep();
        def(value, '__ob__', this);
        if (isArray(value)) {
            walkArray(value);
        }
        else {
            walk(value);
        }
    }

}

/**
 * 遍历 Object 中的属性
 * @param {any} value
 */
export function walk (value) {
    const keys = Object.keys(value);
    for (let i=0; i<keys.length; i++) {
        const key = keys[i];
        defineReactive(value, key);
    }
}

/**
 * 将观察对象/数组的逻辑单独提出来
 * @param {Object|Array} value
 */
export function observe (value) {
    if (value instanceof Observer
        || value instanceof VNode
        || (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer)
    ) {
        return value instanceof Observer ? value : value.__ob__;
    }
    if (!hasOwn(value, '__ob__')
        && (isPlainObject(value) || isArray(value))
    ) {
        return new Observer(value);
    }
}
